package com.xishu.service;

import com.alibaba.fastjson.JSON;
import com.xishu.annotation.dao.*;
import com.xishu.annotation.sort.ShowOrder;
import com.xishu.annotation.valid.UniqueName;
import com.xishu.cache.CacheService;
import com.xishu.config.Config;
import com.xishu.config.Constant;
import com.xishu.dao.DaoUtil;
import com.xishu.entity.AbstractEntity;
import com.xishu.entity.oplog.OpName;
import com.xishu.exception.ResponseStatusException;
import com.xishu.response.ResponseData;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.util.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.reflect.FieldUtils;
import org.apache.logging.log4j.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.xishu.config.Constant.THREAD_LOCAL_VARIABLE_NO_NEED_WRITE_OPERATE_LOG;
import static com.xishu.util.ClassUtil.*;


public class CommonService implements Tools {
    private static Logger logger = LoggerFactory.getLogger(CommonService.class);

    private static CommonService instance = new CommonService();

    private Config config = Config.getInstance();

    private JdbcTemplate getJdbcTemplate() {
        return BeanUtil.getBean(JdbcTemplate.class);
    }

    private CommonService() {
    }

    public static CommonService getInstance() {
        return instance;
    }

    /**
     * 根据数据返回响应
     *
     * @param oIn
     * @return
     */
    public ResponseData createResponse(Object oIn) throws Exception {
        Object o = ClassUtil.clone(oIn);
        try {
            responseFormatDouble(o);
        } catch (IllegalAccessException e) {
            logger.error("e", e);
        } catch (Exception e) {
            logger.error("e", e);
        }

        JsonConfig jsonConfig = new JsonConfig();
        jsonConfig.registerJsonValueProcessor(Date.class, new JsonBooleanValueProcessor());

        if (o instanceof String) {
            return new ResponseData(o);
        }

        if (o instanceof Number) {
            return new ResponseData(o);
        }

        if (o instanceof Boolean) {
            return new ResponseData(o);
        }

        if (o instanceof Iterable) {
            return new ResponseData(o);
        }

        ClassUtil.getAllField(o).stream().filter(f -> {
            Hidden hidden = f.getAnnotation(Hidden.class);
            return hidden != null && hidden.hidden();
        }).forEach(f -> {
            try {
                f.set(o, null);
            } catch (IllegalAccessException e) {
                logger.error("e", e);
            }
        });

        return new ResponseData(o);
    }

    /**
     * 检查唯一性
     *
     * @param t
     * @param <T>
     */
    public <T extends AbstractEntity> void checkUnique(T t, boolean updateAction, ResponseStatus uniqueCheckStatus) throws Exception {
        if (uniqueCheckStatus == null) {
            uniqueCheckStatus = ResponseStatus.NAME_EXISTS;
        }
        Stream<Field> fieldNameList = ClassUtil.getAllField(t).stream().filter(f -> {
            return f.getAnnotation(UniqueName.class) != null;
        });

        List<Field> fieldList = fieldNameList.collect(Collectors.toList());

        if (CollectionUtils.isEmpty(fieldList)) {
            return;
        }

        AbstractEntity req = t.getClass().newInstance();

        List<Field> uniqueList = fieldList.stream().filter(p -> {
            UniqueName annotation = p.getAnnotation(UniqueName.class);
            return !annotation.union();
        }).collect(Collectors.toList());

        //依次判断，只要有一个重复了，就报错,只校验值不为空的
        for (Field f : uniqueList) {
            try {
                if (f.get(t) != null) {
                    f.set(req, f.get(t));
                    //唯一性的校验，必须要相等，不能够模糊查询
                    ArrayList<Specification<Object>> specificationArrayList = new ArrayList<>();
                    Specification<Object> specification = DaoUtil.getInstance().sqlEq(f.getName(), f.get(t));
                    specificationArrayList.add(DaoUtil.getInstance().sqlEq("flagDelete", false));
                    specificationArrayList.add(specification);
                    specification = DaoUtil.getInstance().and(specificationArrayList);

                    JpaSpecificationExecutor jpaSpecificationExecutor = DaoUtil.getInstance().getDao(t);
                    List<AbstractEntity> findList = jpaSpecificationExecutor.findAll(specification);

                    //更新校验,如果有相同的，必须ID相等
                    if (t.getId() != null) {
                        if (CollectionUtils.isNotEmpty(findList) && findList.get(0).getId() != t.getId()) {
                            VerifyUtil.throwError(uniqueCheckStatus);
                        }
                    } else {
                        //创建校验
                        if (CollectionUtils.isNotEmpty(findList)) {
                            VerifyUtil.throwError(uniqueCheckStatus);
                        }
                    }

                }

            } catch (Exception e) {
                logger.error("e", e);
                VerifyUtil.throwError(uniqueCheckStatus);
            }
        }

        //联合主键校验
        List<Field> unionList = fieldList.stream().filter(p -> {
            UniqueName annotation = p.getAnnotation(UniqueName.class);
            return annotation.union();
        }).collect(Collectors.toList());

        //不能为null时，一定要校验
        if (isNotEmpty(unionList)) {
            //过滤不为空的字段
            List<Field> filterNotNullFieldList = unionList.stream().filter(f -> {
                f.setAccessible(true);
                try {
                    return f.get(t) != null;
                } catch (IllegalAccessException e) {
                    logger.error("e");
                    return false;
                }
            }).collect(Collectors.toList());


            if (isEmpty(filterNotNullFieldList)) {
                return;
            }

            if (updateAction) {
                //从数据库里面读出来，然后将请求里面的参数写回来
                Long id = t.getId();
                AbstractEntity entityInDb = findEntity(id, t.getClass());
                for (Field field : unionList) {
                    field.setAccessible(true);

                    //为空的值，从数据库里面读取后再设置回来
                    if (field.get(t) == null) {
                        org.apache.commons.beanutils.BeanUtils.copyProperty(t, field.getName(), field.get(entityInDb));
                    }
                }
            }

            AbstractEntity testObject = t.getClass().newInstance();
            ArrayList<Specification<Object>> specificationArrayList = new ArrayList<>();

            for (Field field : unionList) {
                field.setAccessible(true);

                //必须每个值都要传递过来
                VerifyUtil.verify(() -> {
                    try {
                        return field.get(t) != null;
                    } catch (Exception e) {
                        logger.error("e", e);
                        return false;
                    }
                });

                field.set(testObject, field.get(t));
                Specification<Object> specification = DaoUtil.getInstance().sqlEq(field.getName(), field.get(t));
                specificationArrayList.add(specification);
            }

            //再添加没有删除的数据
            specificationArrayList.add(DaoUtil.getInstance().sqlEq("flagDelete", false));
            specificationArrayList.add(DaoUtil.getInstance().sqlEq("entity", true));

            Specification specification = DaoUtil.getInstance().and(specificationArrayList);
            JpaSpecificationExecutor jpaSpecificationExecutor = DaoUtil.getInstance().getDao(t);
            List<AbstractEntity> findList = jpaSpecificationExecutor.findAll(specification);

            if (updateAction) {
                if (isNotEmpty(findList)) {
                    //找到的实体刚好是自己，不用处理
                    if (findList.size() == 1 && findList.get(0).getId().longValue() == t.getId().longValue()) {
                        return;
                    }

                    //找到了其它实体，则报已存在
                    VerifyUtil.throwError(uniqueCheckStatus);
                }
            } else {
                if (CollectionUtils.isNotEmpty(findList)) {
                    VerifyUtil.throwError(uniqueCheckStatus);
                }
            }
        }

    }

    public boolean isFieldNotEmpty(Field field, Object t) throws IllegalAccessException {
        field.setAccessible(true);
        Object value = field.get(t);

        return value != null;
    }

    /**
     * 处理字段的映射
     *
     * @param t
     * @param <T>
     */
    public <T extends AbstractEntity> void dealFieldMapping(T t, boolean serial) {
        List<Field> fieldList = Arrays.stream(t.getClass().getDeclaredFields()).filter(f -> {
            try {
                f.setAccessible(true);
                return f.getAnnotation(FieldMapping.class) != null && isFieldNotEmpty(f, t);
            } catch (IllegalAccessException e) {
                logger.error("e", e);
                return false;
            }
        }).collect(Collectors.toList());

        if (isEmpty(fieldList)) {
            logger.debug("class {} field mapping is empty", t.getClass().getName());
            return;
        }

        fieldList.forEach(f -> {
            FieldMapping fieldMapping = f.getAnnotation(FieldMapping.class);
            String desFieldName = fieldMapping.desField();
            Field desField = ClassUtil.getInstance().getField(t.getClass(), desFieldName);

            //序列化
            if (fieldMapping.serialize() && serial) {
                if (desField != null) {
                    try {
                        if (!fieldMapping.isObject()) {
                            //数组的序列化
                            desField.setAccessible(true);
                            desField.set(t, new com.alibaba.fastjson.JSONArray((List) f.get(t)).toString());
                        } else {
                            //对象的序列化
                            desField.setAccessible(true);
                            desField.set(t, JSONObject.fromObject(f.get(t)).toString());
                        }
                    } catch (IllegalAccessException e) {
                        logger.error("e", e);
                    }
                }
            } else if (!fieldMapping.serialize() && !fieldMapping.isObject() && !serial) {
                //反序列化，并且是数组
                if (desField != null) {
                    try {
                        desField.setAccessible(true);
                        logger.debug("field mapping field is {}", f.getName());
                        Object value = f.get(t);

                        //没有值，那么直接返回
                        if (value == null || isEmpty(value.toString())) {
                            return;
                        }

                        JSONArray jsonArray = JSONArray.fromObject(f.get(t));

                        if (equals(fieldMapping.genericType(), LONG_TYPE)) {
                            List list = JSONArray.toList(jsonArray, Long.valueOf(0), new JsonConfig());
                            desField.set(t, list.stream().map(p -> Long.valueOf(p.toString())).collect(Collectors.toList()));
                        } else if (equals(fieldMapping.genericType(), DOUBLE_TYPE)) {
                            List list = JSONArray.toList(jsonArray, Double.valueOf(0), new JsonConfig());
                            desField.set(t, list);
                        } else if (equals(fieldMapping.genericType(), STRING_TYPE)) {
                            List list = JSONArray.toList(jsonArray, String.valueOf(0), new JsonConfig());
                            desField.set(t, list);
                        } else if (equals(fieldMapping.genericType(), INTEGER_TYPE)) {
                            List list = JSONArray.toList(jsonArray, Integer.valueOf(0), new JsonConfig());
                            desField.set(t, list);
                        } else {
                            List<?> objects = JSON.parseArray(f.get(t).toString(), Class.forName(fieldMapping.genericType()));
                            desField.set(t, objects);
                        }
                    } catch (IllegalAccessException | ClassNotFoundException e) {
                        logger.error("error field is {}", f.getName());
                        logger.error("e", e);
                    }
                }
            } else if (!fieldMapping.serialize() && fieldMapping.isObject() && !serial) {
                //反序列化，并且是对象
                try {
                    if (desField != null && f.get(t) != null) {
                        desField.setAccessible(true);
                        if (f.get(t) != null) {
                            String jsonString = f.get(t).toString();
                            if (isNotEmpty(jsonString)) {
                                JSONObject jsonObject = JSONObject.fromObject(jsonString);
                                Object bean = JSONObject.toBean(jsonObject, Class.forName(fieldMapping.genericType()));
                                desField.set(t, bean);
                            }
                        } else {
                            logger.error("can not find the field, {}", f.getName());
                        }
                    }
                } catch (IllegalAccessException | ClassNotFoundException e) {
                    logger.error("e", e);
                }
            }
        });
    }

    /**
     * 创建对象
     *
     * @param t
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws ResponseStatusException
     * @throws InstantiationException
     */
    public <T extends AbstractEntity> ResponseData createObject(T t) throws Exception {
        return createObject(t, null, true, null);
    }

    /**
     * 创建对象
     *
     * @param t
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws ResponseStatusException
     * @throws InstantiationException
     */
    public <T extends AbstractEntity> ResponseData createObject(T t, Consumer<T> consumer) throws Exception {
        return createObject(t, consumer, true, null);
    }

    /**
     * 创建对象
     *
     * @param t
     * @param <T>
     */
    public <T extends AbstractEntity> ResponseData createObject(T t, Consumer<T> consumer, boolean uniqueCheck, ResponseStatus uniqueCheckStatus) throws Exception {
        VerifyUtil.verify(() -> t.getId() == null);

        if (t.createTime == null) {
            t.createTime = System.currentTimeMillis();
        }

        //更新时间和创建时间一致
        t.updateTime = t.createTime;

        t.createDate = DateUtil.formatDate(t.createTime);
        t.updateDate = t.createDate;
        t.setFlagDelete(false);
        t.setEntity(true);

        //是否需要检测唯一必一，在备份的时候不需要检测
        if (uniqueCheck) {
            checkUnique(t, false, uniqueCheckStatus);
        }

        //默认创建实体，不是备份的数据
        if (t.entity == null) {
            t.entity = true;
        }

        String requestId = ServletUtil.getRequestId();

        if (isNotEmpty(requestId)) {
            t.addRequestId(requestId);
        }

        encrypt(t);

        dealFieldMapping(t, true);
        t.addRequestId(ServletUtil.getRequestId());

        //如果有默认值，添加默认值
        dealDefaultValueWithAnnotation(t);

        //真实创建对象
        logger.info("start create object {} class {}", t.getId(), t.getClass().getSimpleName());
        DaoUtil.getInstance().createEntity(t);
        logger.info("create object {} class {}", t.getId(), t.getClass().getSimpleName());

        //如果不写日志，则不写
        String noNeedWriteOperateLog = ThreadContext.get(THREAD_LOCAL_VARIABLE_NO_NEED_WRITE_OPERATE_LOG);

        //为空，表示需要写日志
        if (noNeedWriteOperateLog == null) {
            OpLogService.getInstance().createLog_createObject(t);
        }

        if (consumer != null) {
            consumer.accept(t);
        }

        return createResponse(t);
    }

    /**
     * 处理注解的默认值
     *
     * @param object
     */
    public void dealDefaultValueWithAnnotation(Object object) {
        try {
            List<Field> allField = ClassUtil.getAllField(object);

            for (Field field : allField) {
                defaultFieldDefaultValue(object, field);
            }
        } catch (Exception e) {
            logger.error("e", e);
        }
    }

    private void defaultFieldDefaultValue(Object object, Field field) throws IllegalAccessException {
        Object value = field.get(object);

        if (value != null) {
            return;
        }

        DefaultValue defaultValue = field.getAnnotation(DefaultValue.class);
        //没有默认值要处理
        if (defaultValue == null) {
            return;
        }

        //值为空，并且有设置默认值，那么添加默认值,当前的默认值先支持基本数据类型，以及String
        String filedTypeName = ClassUtil.getFiledTypeName(field);

        if (isFieldLong(filedTypeName)) {
            field.set(object, Long.valueOf(defaultValue.defaultValue()));
        } else if (isFieldBoolean(filedTypeName)) {
            field.set(object, Boolean.valueOf(defaultValue.defaultValue()));
        } else if (isFieldInteger(filedTypeName)) {
            field.set(object, Integer.valueOf(defaultValue.defaultValue()));
        } else if (isFieldFloat(filedTypeName)) {
            field.set(object, Float.valueOf(defaultValue.defaultValue()));
        } else if (isFieldDouble(filedTypeName)) {
            field.set(object, Double.valueOf(defaultValue.defaultValue()));
        } else if (isFieldString(filedTypeName)) {
            field.set(object, defaultValue.defaultValue());
        } else if (isFieldList(filedTypeName)) {
            field.set(object, new ArrayList<>());
        }

        return;
    }

    /**
     * 不带处理后的参数更新
     *
     * @param t
     * @param <T>
     * @return
     * @throws ResponseStatusException
     */
    public <T extends AbstractEntity> ResponseData updateObject(T t, Consumer<T> consumer) throws Exception {
        return updateObject(t, consumer, null, null);
    }

    /**
     * 不带处理后的参数更新
     *
     * @param t
     * @param <T>
     * @return
     * @throws ResponseStatusException
     */
    public <T extends AbstractEntity> ResponseData updateObject(T t) throws Exception {
        return updateObject(t, null, null, null);
    }

    /**
     * 不带处理后的参数更新
     *
     * @param t
     * @param <T>
     * @return
     * @throws ResponseStatusException
     */
    public <T extends AbstractEntity> ResponseData modifyObject(T t) throws Exception {
        return updateObject(t, null, null, null);
    }

    /**
     * 更新对象，先从数据库里面查询出来，再依次赋值
     *
     * @param t
     * @param <T>
     */

    public <T extends AbstractEntity> ResponseData updateObject(T t, Consumer<T> consumer, Function<T, ResponseStatus> validator, ResponseStatus uniqueCheckStatus) throws Exception {
        Long id = t.getId();
        VerifyUtil.verify(() -> id != null);

        //用commonService里面的fetch方法，里面做了反序列化的操作
        AbstractEntity queryRequest = t.getClass().newInstance();
        queryRequest.setId(id);
        AbstractEntity entityInDb = fetchById(queryRequest);
        t.setEntity(true);
        checkUnique(t, true, uniqueCheckStatus);

        //加密处理
        encrypt(t);

        dealFieldMapping(t, true);

        boolean adminUser = ServletUtil.isAdminUser();

        //过滤出哪些字段不能修改
        List<String> notModifyFields = Arrays.stream(t.getClass().getDeclaredFields()).filter(f -> {
            try {
                f.setAccessible(true);

                //admin账号所有的内容均可以修改
                if (adminUser) {
                    return f.get(t) == null;
                } else {
                    return (f.getAnnotation(NotModify.class) != null) || f.get(t) == null;
                }
            } catch (IllegalAccessException e) {
                return true;
            }
        }).map(f -> f.getName()).collect(Collectors.toList());

        notModifyFields.add("requestId");
        notModifyFields.add("createDate");
        notModifyFields.add("createTime");

        //添加更新时间
        t.setUpdateTime(System.currentTimeMillis());
        t.setUpdateDate(DateUtil.formatDate(t.getUpdateTime()));

        for (String notModifyField : notModifyFields) {
            logger.debug("ignore field is {}", notModifyField);
        }

        BeanUtils.copyProperties(t, entityInDb, notModifyFields.toArray(new String[notModifyFields.size()]));
        DaoUtil daoUtil = DaoUtil.getInstance();
        entityInDb.addRequestId(ServletUtil.getRequestId());

        //入库前先校验
        if (validator != null) {
            ResponseStatus responseStatus = validator.apply((T) entityInDb);
            //校验出错了，那么抛出对应的错误码
            if (responseStatus != null && responseStatus != ResponseStatus.OK) {
                VerifyUtil.throwError(responseStatus);
            }
        }

        daoUtil.updateEntity(entityInDb);

        CacheService.getInstance().putObject(entityInDb, true);

        if (consumer != null) {
            consumer.accept(t);
        }

        //实现了操作日志的类，记录操作日志，如果没有实现操作日志的类，需要单独记录日志
        if (t instanceof OpName) {
            OpName opName = (OpName) t;

            String[] fieldNameList = opName.fieldName();

            if (isNotEmpty(fieldNameList)) {
                logger.info("fieldNameList is {}", String.join(":", fieldNameList));
            }

            List<String> fieldValueList = Arrays.stream(fieldNameList).map(f -> {
                Field field = ClassUtil.getInstance().getField(t.getClass(), f);
                try {
                    return field.get(entityInDb).toString();
                } catch (Exception e) {
                    logger.error("e", e);
                    return "";
                }
            }).collect(Collectors.toList());

            String opFieldValue = String.join(":", fieldValueList.toArray(new String[fieldValueList.size()]));

            opName.setOpName(opFieldValue);
            OpLogService.getInstance().createLog(t);
        }


        return ResponseData.emptyResponse();
    }

    /**
     * 创建查询条件
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> Specification<T> createSpecification(T t) {
        logger.info("class name is {}", t.getClass().getName());

        List<Field> fieldList = ClassUtil.getAllField(t).stream().filter(f -> {
            try {
                f.setAccessible(true);

                return FieldUtils.readField(f, t, true) != null && !f.getName().equals("serialVersionUID");
            } catch (IllegalAccessException e) {
                logger.error("e", e);
                return false;
            }
        }).collect(Collectors.toList());

        List<Specification<T>> specificationList = fieldList.stream().map(f -> {
            return fieldToSpecification(t, f, true);
        }).filter(p -> p != null).collect(Collectors.toList());

        specificationList = dealOrCondition(t, specificationList);

        return DaoUtil.getInstance().and(specificationList);
    }

    /**
     * 字段转查询条件
     *
     * @param t
     * @param f
     * @param <T>
     * @return
     */
    private <T> Specification<T> fieldToSpecification(T t, Field f, boolean ignoreGroupField) {
        try {
            Field ignoreLikeField = ClassUtil.getInstance().getField(t.getClass(), "ignoreLike");

            boolean ignoreLike = false;

            if (ignoreLikeField != null && ignoreLikeField.get(t) != null && Boolean.parseBoolean(ignoreLikeField.get(t).toString())) {
                ignoreLike = true;
            }

            Transient aTransient = f.getAnnotation(Transient.class);

            Search search = f.getAnnotation(Search.class);

            //不搜索，也不保存，不用处理
            if (search == null && aTransient != null) {
                return null;
            }

            //忽略按照组查询，并且当前正好是按照组查询，那么忽略掉
            if (ignoreGroupField && search != null && isNotEmpty(search.groupName())) {
                return null;
            }

            //需要搜索的情况
            if (search != null) {
                if (search.prefixLike()) {
                    //模糊查询
                    logger.info("will add search field {}, ignore like {}", search.fieldName(), ignoreLike);

                    //忽略模糊查询的时候，就直接查询
                    if (ignoreLike) {
                        return (Specification<T>) DaoUtil.getInstance().sqlEq(f.getName(), f.get(t));
                    }

                    return (Specification<T>) DaoUtil.getInstance().prefixLike(search.fieldName(), f.get(t).toString());
                } else if (search.like()) {
                    //模糊查询
                    logger.info("will add search field {}，ignore like {}", search.fieldName(), ignoreLike);

                    if (ignoreLike) {
                        return (Specification<T>) DaoUtil.getInstance().sqlEq(f.getName(), f.get(t));
                    }

                    return (Specification<T>) DaoUtil.getInstance().sqlLike(f.getName(), f.get(t).toString());
                } else if (search.gt()) {
                    Field field = ClassUtil.getInstance().getField(t.getClass(), search.fieldName());

                    if (field == null) {
                        logger.debug("some error field, {}", search.fieldName());
                    }

                    logger.debug("will add search field {}, value is {}", search.fieldName(), f.get(t));

                    if (field != null) {
                        String fieldTypeName = field.getType().getName();
                        if (equals(fieldTypeName, "java.lang.Long")) {
                            return (Specification<T>) DaoUtil.getInstance().sqlGt(search.fieldName(), (long) f.get(t));
                        } else if (equals(fieldTypeName, "java.lang.Double")) {
                            return (Specification<T>) DaoUtil.getInstance().sqlGt(search.fieldName(), (double) f.get(t));
                        } else if (equals(fieldTypeName, "java.lang.Integer")) {
                            return (Specification<T>) DaoUtil.getInstance().sqlGt(search.fieldName(), (int) f.get(t));
                        }
                    }

                } else if (search.gte()) {
                    Field field = ClassUtil.getInstance().getField(t.getClass(), search.fieldName());

                    if (field == null) {
                        logger.debug("some error field, {}", search.fieldName());
                    }

                    logger.debug("will add search field {}, value is {}", search.fieldName(), f.get(t));

                    if (field != null) {
                        String fieldTypeName = field.getType().getName();
                        if (equals(fieldTypeName, "java.lang.Long")) {
                            return (Specification<T>) DaoUtil.getInstance().sqlGte(search.fieldName(), (long) f.get(t));
                        } else if (equals(fieldTypeName, "java.lang.Double")) {
                            return (Specification<T>) DaoUtil.getInstance().sqlGte(search.fieldName(), (double) f.get(t));
                        } else if (equals(fieldTypeName, "java.lang.Integer")) {
                            return (Specification<T>) DaoUtil.getInstance().sqlGte(search.fieldName(), (int) f.get(t));
                        }
                    }
                } else if (search.lte()) {
                    Field field = ClassUtil.getInstance().getField(t.getClass(), search.fieldName());

                    if (field == null) {
                        logger.debug("some error field, {}", search.fieldName());
                    }

                    logger.debug("will add search field {}, value is {}", search.fieldName(), f.get(t));

                    if (field != null) {
                        String fieldTypeName = field.getType().getName();
                        if (equals(fieldTypeName, "java.lang.Long")) {
                            return (Specification<T>) DaoUtil.getInstance().sqlLte(search.fieldName(), (long) f.get(t));
                        } else if (equals(fieldTypeName, "java.lang.Double")) {
                            return (Specification<T>) DaoUtil.getInstance().sqlLte(search.fieldName(), (double) f.get(t));
                        } else if (equals(fieldTypeName, "java.lang.Integer")) {
                            return (Specification<T>) DaoUtil.getInstance().sqlLte(search.fieldName(), (int) f.get(t));
                        }
                    }
                } else if (search.in()) {
                    //传了空的数组，那么不处理
                    if (f.get(t) == null || isEmpty((List<Object>) f.get(t))) {
                        return null;
                    }

                    return (Specification<T>) DaoUtil.getInstance().sqlIn(search.fieldName(), (List<Object>) f.get(t));
                } else if (search.bitAnd()) {
                    String fieldName = search.fieldName();
                    List<Integer> numberList = (List<Integer>) f.get(t);

                    List<Specification<T>> specificationList = new ArrayList<>();

                    for (Integer number : numberList) {
                        Specification specification = DaoUtil.getInstance().bitAnd(fieldName, number);
                        specificationList.add(specification);
                    }

                    return DaoUtil.getInstance().or(specificationList);
                } else if (search.or()) {
                    String fieldList = search.fieldList();
                    String ignoreCaseField = search.ignoreCaseField();
                    List<String> ignoreCaseFieldList = Arrays.asList(ignoreCaseField.split(","));

                    String[] filedNameList = fieldList.split(",");
                    List<Specification<T>> specificationList = Arrays.stream(filedNameList).map(fieldName -> {
                        try {
                            if (!ignoreCaseFieldList.contains(fieldName)) {
                                return (Specification<T>) DaoUtil.getInstance().sqlEq(fieldName, f.get(t));
                            } else {
                                //如果需要忽略大小写
                                return (Specification<T>) DaoUtil.getInstance().sqlEq(fieldName, f.get(t).toString().toLowerCase());
                            }
                        } catch (IllegalAccessException e) {
                            return null;
                        }
                    }).collect(Collectors.toList());

                    return DaoUtil.getInstance().or(specificationList);
                } else if (search.orLike()) {
                    String fieldList = search.fieldList();
                    String[] filedNameList = fieldList.split(",");
                    List<Specification<T>> specificationList = Arrays.stream(filedNameList).map(fieldName -> {
                        try {
                            return (Specification<T>) DaoUtil.getInstance().sqlLike(fieldName, f.get(t));
                        } catch (IllegalAccessException e) {
                            return null;
                        }
                    }).collect(Collectors.toList());

                    return DaoUtil.getInstance().or(specificationList);
                } else if (search.exist()) {
                    String fieldName = search.fieldName();
                    return DaoUtil.getInstance().sqlExist(fieldName);
                } else if (search.isNull()) {
                    String fieldName = search.fieldName();
                    return DaoUtil.getInstance().sqlNull(fieldName);
                } else if (search.ignore()) {
                    //忽略查询
                    return null;
                }
            }

            logger.debug("will add search field {}, value {}", f.getName(), f.get(t));
            return (Specification<T>) DaoUtil.getInstance().sqlEq(f.getName(), f.get(t));
        } catch (IllegalAccessException e) {
            logger.info("e", e);
            return null;
        }
    }

    /**
     * 处理或逻辑
     *
     * @param t
     * @param andSpecificationList
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> List<Specification<T>> dealOrCondition(T t, List<Specification<T>> andSpecificationList) {
        List<Field> fieldList = ClassUtil.getAllField(t).stream().filter(f -> {
            try {
                f.setAccessible(true);
                return f.get(t) != null;
            } catch (IllegalAccessException e) {
                logger.error("e", e);
                return false;
            }
        }).collect(Collectors.toList());


        List<Field> groupFieldList = fieldList.stream().filter(f -> {
            Search annotation = f.getAnnotation(Search.class);
            return annotation != null && isNotEmpty(annotation.groupName());
        }).collect(Collectors.toList());

        Map<String, List<Field>> groupMapFieldList = groupFieldList.stream().collect(Collectors.groupingBy(f -> {
            Search search = f.getAnnotation(Search.class);
            return search.groupName();
        }));

        //分组后，每一组都需要有值，并且求或值，如果没有值，那么不加入查询条件
        for (List<Field> groupQueryField : groupMapFieldList.values()) {
            List<Specification<T>> specificationOrList = new ArrayList<>();
            for (Field field : groupQueryField) {
                try {
                    field.setAccessible(true);
                    if (field.get(t) != null) {
                        Specification<T> tSpecification = fieldToSpecification(t, field, false);
                        specificationOrList.add(tSpecification);
                    }
                } catch (IllegalAccessException e) {
                    logger.error("e", e);
                }
            }

            //最后将或语句转成一个查询条件
            if (isNotEmpty(specificationOrList)) {
                Specification orSpecification = DaoUtil.getInstance().or(specificationOrList);
                andSpecificationList.add(orSpecification);
            }
        }

        return andSpecificationList;
    }

    /**
     * 查询所有的结果
     *
     * @param tClass
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T extends AbstractEntity> List<T> searchAll(Class<T> tClass) throws Exception {
        T instance = tClass.newInstance();
        return searchAll(instance);
    }

    /**
     * 查询所有的结果
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> List<T> searchAll(T t) {
        long startTime = System.currentTimeMillis();
        addDeleteFlagAndEntity(t);

        Specification<T> specification = createSpecification(t);
        JpaSpecificationExecutor jpaSpecificationExecutor = DaoUtil.getInstance().getDao(t);
        List list = jpaSpecificationExecutor.findAll(specification);

        for (Object o : list) {
            dealFieldMapping((T) o, false);
            //如果有加密数据，需要解密处理
//            decrypt(o);
            dealDefaultValueWithAnnotation(o);
        }


        long endTime = System.currentTimeMillis();
        logger.info("cost time in search all {}", endTime - startTime);

        return list;
    }

    /**
     * 按照搜索条件来计数
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> Long count(T t) {
        addDeleteFlagAndEntity(t);

        Specification<T> specification = createSpecification(t);
        JpaSpecificationExecutor jpaSpecificationExecutor = DaoUtil.getInstance().getDao(t);
        return jpaSpecificationExecutor.count(specification);
    }

    /**
     * 分页查询
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> Page<T> search(T t) {
        addDeleteFlagAndEntity(t);

        Specification<T> specification = createSpecification(t);

        PageRequest pageRequest = null;

        if (isEmpty(t.sortField)) {
            pageRequest = PageRequest.of(getPageNumber(t), getPageSize(t));
        } else {
            Sort.Direction direction = null;

            if (equalsIgnoreCase(t.sortType, "desc")) {
                direction = Sort.Direction.DESC;
            } else direction = Sort.Direction.ASC;

            pageRequest = PageRequest.of(getPageNumber(t), getPageSize(t), direction, t.sortField);
        }

        JpaSpecificationExecutor dao = DaoUtil.getInstance().getDao(t);

        Page all = dao.findAll(specification, pageRequest);

        all.forEach(p -> dealFieldMapping((T) p, false));
        all.forEach(p -> dealDefaultValueWithAnnotation(p));
        return all;
    }

    /**
     * 获取查询结果
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> List<T> searchList(T t) {
        Page<T> search = search(t);
        return search.getContent();
    }

    /**
     * 查询某一条记录
     *
     * @param t
     * @param <T>
     */
    public <T extends AbstractEntity> T searchOne(T t) {
        Page<T> search = search(t);

        if (search.getTotalElements() == 0) {
            return null;
        }

        T result = search.getContent().get(0);
        dealFieldMapping(result, false);
        dealDefaultValueWithAnnotation(result);
//        decrypt(result);
        return result;
    }

    /**
     * 查询对象是否存在
     *
     * @param id
     * @param tClass
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T extends AbstractEntity> Optional<T> searchOneOptional(Long id, Class<T> tClass) throws Exception {
        if (id == null) {
            return Optional.empty();
        }

        T t = tClass.newInstance();
        t.setId(id);
        return searchOneOptional(t);
    }

    /**
     * 查询对象
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> Optional<T> findOneOptional(T t) {
        return searchOneOptional(t);
    }

    /**
     * 查询某一条记录
     *
     * @param t
     * @param <T>
     */
    public <T extends AbstractEntity> Optional<T> searchOneOptional(T t) {
        long startTime = System.currentTimeMillis();
        Page<T> search = search(t);

        if (search.getTotalElements() == 0) {
            logger.info("do not get the entity time {}", System.currentTimeMillis() - startTime);
            return Optional.empty();
        }

        T result = search.getContent().get(0);
        dealFieldMapping(result, false);
        dealDefaultValueWithAnnotation(result);
        logger.info("get the entity time {}", System.currentTimeMillis() - startTime);
        return Optional.of(result);
    }

    /**
     * 分页查询
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> ResponseData searchResponse(T t) throws Exception {
        return searchResponse(t, null, null);
    }

    /**
     * 分页查询
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> ResponseData searchResponse(T t, Consumer<T> afterQuery) throws Exception {
        return searchResponse(t, afterQuery, null);
    }

    /**
     * 空值
     *
     * @param t
     * @param afterQuery
     * @param filterResult
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> ResponseData searchResponse(T t, Consumer<T> afterQuery, Function<List<T>, List<T>> filterResult) throws Exception {
        return searchResponse(t, afterQuery, filterResult, null);
    }

    public <T extends AbstractEntity> int getPageNumber(T t) {
        Integer pageNumber = t.getPageNumber();

        if (pageNumber == null) {
            pageNumber = 0;
        } else {
            pageNumber = pageNumber - 1;
        }

        if (pageNumber < 0) {
            pageNumber = 0;
        }

        return pageNumber;
    }

    public <T extends AbstractEntity> int getPageSize(T t) {
        if (t.pageSize == null) {
            return config.getShowPageSize();
        }

        return t.pageSize;
    }

    /**
     * 分页查询
     *
     * @param t
     * @param <T>
     * @param filterResult 查询过后的结果过滤
     * @return
     */
    public <T extends AbstractEntity> ResponseData searchResponse(T t, Consumer<T> afterQuery, Function<List<T>, List<T>> filterResult, Boolean responseNumberNullValue) throws Exception {
        addDeleteFlagAndEntity(t);

        Specification<T> specification = createSpecification(t);

        PageRequest pageRequest = null;
        if (isEmpty(t.sortField)) {
            pageRequest = PageRequest.of(getPageNumber(t), getPageSize(t));
        } else {
            Sort.Direction direction = null;

            if (equalsIgnoreCase(t.sortType, "desc")) {
                direction = Sort.Direction.DESC;
            } else direction = Sort.Direction.ASC;

            pageRequest = PageRequest.of(getPageNumber(t), getPageSize(t), direction, t.sortField);
        }

        JpaSpecificationExecutor dao = DaoUtil.getInstance().getDao(t);
        Page page = dao.findAll(specification, pageRequest);

        //处理字段映射
        for (Object o : page.getContent()) {
            dealFieldMapping((T) o, false);
        }

        if (afterQuery != null) {
            page.getContent().forEach(afterQuery);
        }

        List searchResult = page.getContent();

        if (filterResult != null) {
            searchResult = filterResult.apply(searchResult);
        }

        JsonConfig jsonConfig = new JsonConfig();
        jsonConfig.registerJsonValueProcessor(Boolean.class, new JsonBooleanValueProcessor());
        if (getBoolean(responseNumberNullValue)) {
            jsonConfig.registerJsonValueProcessor(Long.class, new JsonNumberValueProcessor());
            jsonConfig.registerJsonValueProcessor(Integer.class, new JsonNumberValueProcessor());
            jsonConfig.registerJsonValueProcessor(Double.class, new JsonNumberValueProcessor());
            jsonConfig.registerJsonValueProcessor(Float.class, new JsonNumberValueProcessor());
        }

        //在显示前，最后处理不显示的字段
        for (Object o : searchResult) {
            List<Field> allField = ClassUtil.getAllField(o);
            List<Field> notShowField = allField.stream().filter(p -> p.getAnnotation(Encrypt.class) != null).collect(Collectors.toList());

            //不显示的字段，用空字符来显示
            for (Field field : notShowField) {
                field.setAccessible(true);
                field.set(o, null);
            }

            responseFormatDouble(o);
        }

        //明确不显示的字段隐藏
        for (Object o : searchResult) {
            //过滤第一层
            hiddenObjectValue(o);

            //过滤第二层
            ClassUtil.getAllField(o).stream().filter(f -> {
                Hidden hidden = f.getAnnotation(Hidden.class);
                return hidden != null && hidden.enterHidden();
            }).forEach(f -> {
                try {
                    Object fieldValue = f.get(o);
                    if (fieldValue != null) {
                        hiddenObjectValue(fieldValue);
                    }
                } catch (IllegalAccessException e) {
                    logger.error("e", e);
                }
            });
        }

        //处理默认值
        for (Object o : searchResult) {
            dealDefaultValueWithAnnotation(o);
        }

        ResponseData responseData = new ResponseData();
        responseData.setData(searchResult);
        responseData.setPageSize(getPageSize(t));
        responseData.setRealSize(page.getTotalElements());

        //显示过滤过后的大小
        if (filterResult != null) {
            responseData.setSize(page.getTotalElements());
        } //最大100分页
        else if ((page.getTotalElements() / getPageSize(t)) >= 100) {
            responseData.setSize(getPageSize(t) * 100);
        } else {
            responseData.setSize(page.getTotalElements());
        }

        return responseData;
    }

    /**
     * 隐藏数据类型
     *
     * @param o
     */
    private void hiddenObjectValue(Object o) {
        ClassUtil.getAllField(o).stream().filter(f -> {
            Hidden hidden = f.getAnnotation(Hidden.class);
            return hidden != null && hidden.hidden() && !hidden.enterHidden();
        }).forEach(f -> {
            try {
                f.set(o, null);
            } catch (IllegalAccessException e) {
                logger.error("e", e);
            }
        });
    }

    /**
     * 直接删除，不是标删
     *
     * @param t
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public <T extends AbstractEntity> ResponseData delete(T t) throws Exception {
        return delete(t, true, null);
    }

    /**
     * 直接删除，不是标删
     *
     * @param t
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public <T extends AbstractEntity> ResponseData delete(T t, Boolean flagDelete) throws Exception {
        return delete(t, flagDelete, null);
    }

    /**
     * 单个删除，批量删除
     *
     * @param t
     * @param <T>
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public <T extends AbstractEntity> ResponseData delete(T t, Boolean flagDelete, Consumer<T> consumer) throws Exception {
        String feRequest = ThreadContext.get(Constant.FE_REQUEST);

        //前端请求，只能删除固定的一些数据，不能够批量删除
        if (!getBoolean(t.getBeRequest()) && isNotEmpty(feRequest)) {
            VerifyUtil.verify(() -> t.getId() != null || isNotEmpty(t.getIds()));
        }

        if (isNotEmpty(t.getId())) {
            logger.info("will delete object {}", t.getId());

            if (flagDelete == null || flagDelete) {
                T entityInDb = CommonService.getInstance().findEntity(t);
                entityInDb.flagDelete = true;
                directSave(entityInDb);
                deleteFromCache(entityInDb);

                //添加操作日志
                //实现了操作日志的类，记录操作日志，如果没有实现操作日志的类，需要单独记录日志
                if (t instanceof OpName) {
                    OpName opName = (OpName) entityInDb;
                    opName.setOpName(String.format("delete,%s", t.getId()));
                    OpLogService.getInstance().createDeleteLog(entityInDb);
                }
            } else {
                DaoUtil.getInstance().deleteEntity(t);
                deleteFromCache(t);
            }
        } else if (isNotEmpty(t.ids)) {
            logger.info("will multi delete");
            for (Long id : t.ids) {
                if (isNotEmpty(id)) {
                    if (getBoolean(flagDelete)) {
                        T entityInDb = (T) CommonService.getInstance().findEntity(id, t.getClass());
                        entityInDb.flagDelete = true;
                        directSave(entityInDb);
                        deleteFromCache(entityInDb);

                        if (t instanceof OpName) {
                            OpName opName = (OpName) entityInDb;
                            opName.setOpName(String.format("delete,%s,%s", opName.opType(), id));
                            OpLogService.getInstance().createDeleteLog(entityInDb);
                        }

                    } else {
                        AbstractEntity abstractEntity = t.getClass().newInstance();
                        abstractEntity.setId(id);
                        DaoUtil.getInstance().deleteEntity(abstractEntity);
                        deleteFromCache(abstractEntity);
                    }
                }
            }
        } else {
            //按照条件删除,真删
            if (!getBoolean(flagDelete)) {
                //先查询，再删除
                t.flagDelete = null;
                List<T> list = searchAll(t);
                JpaRepository jpa = DaoUtil.getInstance().getJpa(t);
                logger.info("delete all size {}, class {}", list.size(), t.getClass().getName());
                jpa.deleteAll(list);
            } else {
                //按照条件标记删除
                t.flagDelete = null;
                List<T> list = searchAll(t);
                logger.info("flag delete all size {}, class {}", list.size(), t.getClass().getName());
                for (T t1 : list) {
                    t1.setFlagDelete(true);
                    save(t1);
                }
            }
        }

        if (consumer != null) {
            consumer.accept(t);
        }

        logger.debug("delete end");
        return ResponseData.emptyResponse();
    }

    /**
     * 不为空的字段的值
     *
     * @param t
     * @return
     */
    public List<Object> getNotNullValues(Object t) {
        List<Field> fieldList = Arrays.stream(t.getClass().getDeclaredFields()).filter(f -> {
            try {
                f.setAccessible(true);
                return f.get(t) != null;
            } catch (IllegalAccessException e) {
                logger.error("e", e);
                return false;
            }
        }).collect(Collectors.toList());

        return fieldList.stream().map(f -> {
            try {
                return f.get(t);
            } catch (IllegalAccessException e) {
                return null;
            }
        }).filter(f -> f != null).collect(Collectors.toList());
    }

    /**
     * 通过ID来查询，并做反序列化
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> T fetchById(T t) throws Exception {
        AbstractEntity abstractEntity = DaoUtil.getInstance().fetchById(t.getId(), t.getClass());
        dealFieldMapping(abstractEntity, false);
        dealDefaultValueWithAnnotation(abstractEntity);
        return (T) abstractEntity;
    }

    /**
     * 通过ID查询对象，如果不存在，再从数据库里面查询
     *
     * @param id
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> T findEntity(Long id, Class<T> tclass) throws Exception {
        T newInstance = tclass.newInstance();
        newInstance.setId(id);
        return findEntity(newInstance);
    }

    /**
     * 通过ID列表查询列表
     *
     * @param idList
     * @param tclass
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> List<T> findEntity(List<Long> idList, Class<T> tclass) {
        return idList.stream().map(p -> {
            try {
                return findEntity(p, tclass);
            } catch (Exception e) {
                logger.error("e", e);
                return null;
            }
        }).filter(p -> p != null).collect(Collectors.toList());
    }

    /**
     * 通过ID查询对象，如果不存在，再从数据库里面查询
     *
     * @param t
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T extends AbstractEntity> T findEntity(T t) throws Exception {
        return findEntity(t, false);
    }

    /**
     * 从缓存里面读取实体
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> T findEntity_cache(T t) throws Exception {
        if (t == null) {
            return null;
        }

        if (t.getId() == null) {
            return null;
        }

        return CacheService.getInstance().getObject(getEntityKey(t), true);
    }

    /**
     * 通过ID查询对象，如果不存在，再从数据库里面查询
     * 被删除的对象也可以被查询出来
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends AbstractEntity> T findEntity(T t, boolean cache) throws Exception {
        if (!cache) {
            return fetchById(t);
        }

        T entity = CacheService.getInstance().getObject(getEntityKey(t), true);

        //如果找到了，那么直接使用
        if (entity != null) {
            //默认值的处理待定，应该也是可以去掉的
            //dealDefaultValueWithAnnotation(entity);
            return entity;
        }

        //如果没有，则加锁后再读写，以防止数据不一致
        //例如B先读，然后A写，A刷新缓存，B读后再缓存，缓存里面的数据还是没有变化过后的数据

        String lockKey = getEntityKey(t);
        Object lock = LockService.getInstance().getLock(lockKey);

        synchronized (lock) {
            entity = CacheService.getInstance().getObject(getEntityKey(t), true);

            //如果找到了，那么直接使用，不用再次查询
            if (entity != null) {
                //默认值的处理待定，应该也是可以去掉的
                //dealDefaultValueWithAnnotation(entity);
                return entity;
            }

            T entityInDb = fetchById(t);
            CacheService.getInstance().putObject(entityInDb, true);
            return entityInDb;
        }
    }

    /**
     * 从缓存中删除
     *
     * @param t
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T extends AbstractEntity> void deleteFromCache(T t) {
        CacheService.getInstance().deleteObject(getEntityKey(t), true);
    }


    /**
     * 直接保存对象
     *
     * @param t
     * @param <T>
     */
    public <T extends AbstractEntity> void directSave(T t) {
        long startTime = System.currentTimeMillis();
        logger.info("will save id {}, type is {}", t.getId(), t.getClass());
        if (t.getCreateTime() == null) {
            t.createTime = System.currentTimeMillis();
            t.createDate = DateUtil.formatDate(t.createTime);
        }

        if (t.getEntity() == null) {
            t.setEntity(true);
        }

        if (t.getFlagDelete() == null) {
            t.setFlagDelete(false);
        }

        long startMapping = System.currentTimeMillis();
        dealFieldMapping(t, true);
        logger.info("mapping cost time {}", System.currentTimeMillis() - startMapping);

        String requestId = ServletUtil.getRequestId();
        if (isNotEmpty(requestId)) {
            t.addRequestId(requestId);
        }

        DaoUtil.getInstance().updateEntity(t);

        logger.info("save costTime {}", System.currentTimeMillis() - startTime);
    }

    /**
     * 保存对象，并且写入到缓存
     *
     * @param t
     * @param <T>
     */
    public <T extends AbstractEntity> void save(T t) throws Exception {
        //保存的时候，ID一定不能为空，否则在保存之前ID是空，保存之后ID不为空就找不到这个键了，下次再获取锁则会失败了
        VerifyUtil.verify(() -> t.getId() != null);
        directSave(t);
        CacheService.getInstance().putObject(t, true);
    }

    /**
     * 按照条件查询之后，求出某一个字段的最大值
     *
     * @param t
     * @param maxFieldName
     * @param <T>
     * @return
     */
    //todo 通过T来构建查询条件，然后自动过滤出最大值，最小值 ，平均值
    public <T extends AbstractEntity> Long max(T t, String maxFieldName) {
        return 0l;
    }

    /**
     * 是否是中文
     *
     * @param lang
     * @return
     */
    public boolean isZh(String lang) {
        if (isEmpty(lang)) {
            return true;
        }

        return equalsIgnoreCase(lang, "zh");
    }

    /**
     * 设置默认值
     *
     * @param o
     */
    public void setDefaultValue(Object o) {
        try {
            List<Field> allField = ClassUtil.getAllField(o);
            for (Field field : allField) {
                field.setAccessible(true);
                Object value = field.get(o);

                if (value != null) {
                    continue;
                }

                String typeName = field.getType().getName();
                if (equals(typeName, "java.lang.Integer")) {
                    field.set(o, 0);
                } else if (equals(typeName, "java.lang.Long")) {
                    field.set(o, 0l);
                } else if (equals(typeName, "java.lang.Boolean")) {
                    field.set(o, false);
                } else if (equals(typeName, "java.lang.String")) {
                    field.set(o, "");
                } else if (equals(typeName, "java.lang.Double")) {
                    field.set(o, 0d);
                } else if (equals(typeName, "java.util.List")) {
                    field.set(o, new ArrayList<>());
                }
            }
        } catch (Exception e) {
            logger.error("e", e);
        }
    }

    /**
     * 设置默认数据
     *
     * @param list
     */
    public void setDefaultValue(List list) {
        for (Object o : list) {
            setDefaultValue(o);
        }
    }

    /**
     * 加密数据
     *
     * @param o
     */
    public void encrypt(Object o) {
        if (o == null) {
            logger.info("object is null");
            return;
        }

        List<Field> allField = ClassUtil.getAllField(o);
        allField.stream().filter(f -> {
            f.setAccessible(true);
            return f.getAnnotation(Encrypt.class) != null;
        }).forEach(f -> {
            Encrypt annotation = f.getAnnotation(Encrypt.class);

            if (annotation.encrypt()) {
                try {
                    Object value = f.get(o);
                    if (value != null) {
                        String encryptValue = AES.encrypt(value.toString());
                        f.set(o, encryptValue);
                    }
                } catch (IllegalAccessException e) {
                    logger.error("e", e);
                }

            }
        });
    }

    /**
     * 解密数据
     *
     * @param o
     */
    public void decrypt(Object o) {
        if (o == null) {
            logger.info("object is null");
            return;
        }

        List<Field> allField = ClassUtil.getAllField(o);
        allField.stream().filter(f -> {
            f.setAccessible(true);
            return f.getAnnotation(Encrypt.class) != null;
        }).forEach(f -> {
            Encrypt annotation = f.getAnnotation(Encrypt.class);

            if (annotation.encrypt()) {
                try {
                    Object value = f.get(o);
                    if (value != null) {
                        String encryptValue = AES.decrypt(value.toString());

                        //解密成功之后才设置值
                        if (isNotEmpty(encryptValue)) {
                            f.set(o, encryptValue);
                        }
                    }
                } catch (IllegalAccessException e) {
                    logger.error("e", e);
                }

            }
        });
    }

    /**
     * 格式化数字
     *
     * @param o
     */
    public void responseFormatDouble(Object o) throws IllegalAccessException {
        if (o instanceof List) {
            List list = (List) o;
            for (Object o1 : list) {
                responseFormatDouble(o1);
            }

            logger.info("end in format list");
            return;
        }

        if (o == null) {
            logger.info("object is null");
            return;
        }

        List<Field> allField = ClassUtil.getAllField(o);
        for (Field field : allField) {
            String fieldTypeName = field.getType().getName();
            if (fieldTypeName.equals("java.lang.Double")) {
                ResponseFormat responseFormat = field.getAnnotation(ResponseFormat.class);

                //对应版本需要做特殊处理的字段
                if (responseFormat != null && Config.getInstance().getDolaVersion().equalsIgnoreCase(responseFormat.version())) {
                    int digitNumber = responseFormat.doubleDigitNumber();
                    Double doubleValue = (Double) field.get(o);
                    doubleValue = showDouble(doubleValue, digitNumber);
                    field.set(o, doubleValue);
                    continue;
                }

                Double doubleValue = (Double) field.get(o);
                doubleValue = formatMoneyDouble(doubleValue);
                field.set(o, doubleValue);
            } else if (fieldTypeName.contains("com.xishu")) {
                if (field.get(o) != null) {
                    responseFormatDouble(field.get(o));
                }
            } else if (fieldTypeName.contains("java.util.List")) {
                if (field.get(o) != null) {
                    List list = (List) field.get(o);
                    for (Object object : list) {
                        responseFormatDouble(object);
                    }
                }
            }
        }
    }

    /**
     * 满足该条件的所有的任务执行
     *
     * @param reqEntity
     */
    public <T extends AbstractEntity> void doAll(T reqEntity, Consumer<T> consumer) {
        int pageNumber = 1;
        reqEntity.setPageNumber(pageNumber);
        reqEntity.setPageSize(getPageSize(reqEntity));

        while (true) {
            Page<T> pageResult = search(reqEntity);

            //结束条件
            if (isEmpty(pageResult.getContent())) {
                break;
            }

            logger.info("current page is {}", pageNumber);

            //依次处理任务
            for (T t : pageResult.getContent()) {
                consumer.accept(t);
            }
            pageNumber = pageNumber + 1;
            reqEntity.setPageNumber(pageNumber);
        }
    }

    /**
     * 获取查询条件当中的一部分数
     *
     * @param reqEntity
     * @param consumer
     * @param <R>
     * @param <T>
     * @return
     */
    public <R, T extends AbstractEntity> List<R> getAndConvertAll(T reqEntity, Function<T, R> consumer) {
        int pageNumber = 1;
        reqEntity.setPageSize(100);
        List<R> resultList = new ArrayList<R>();

        while (true) {
            Page<T> pageResult = search(reqEntity);

            //结束条件
            if (isEmpty(pageResult.getContent())) {
                break;
            }

            //依次处理任务
            for (T t : pageResult.getContent()) {
                resultList.add(consumer.apply(t));
            }
            pageNumber = pageNumber + 1;
            reqEntity.setPageNumber(pageNumber);
        }

        return resultList;
    }

    /**
     * 新產生一個實體，並且帶默認值
     *
     * @param tClass
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T> T newEntity(Class<T> tClass) throws Exception {
        T instance = tClass.newInstance();
        dealDefaultValueWithAnnotation(instance);
        return instance;
    }

    /**
     * @param t
     * @param number
     * @return
     */
    public <T extends AbstractEntity> List<T> findLimit(T t, int number) {
        addDeleteFlagAndEntity(t);

        Specification<T> specification = createSpecification(t);
        t.setPageNumber(0);
        t.setPageSize(number);
        t.setSortField(new String[]{"createTime"});
        t.setSortType("desc");

        PageRequest pageRequest = null;

        if (isEmpty(t.sortField)) {
            pageRequest = PageRequest.of(getPageNumber(t), getPageSize(t));
        } else {
            Sort.Direction direction = null;

            if (equalsIgnoreCase(t.sortType, "desc")) {
                direction = Sort.Direction.DESC;
            } else direction = Sort.Direction.ASC;

            pageRequest = PageRequest.of(getPageNumber(t), getPageSize(t), direction, t.sortField);
        }


        JpaSpecificationExecutor dao = DaoUtil.getInstance().getDao(t);
        Page page = dao.findAll(specification, pageRequest);
        List list = page.getContent();

        for (Object o : list) {
            dealFieldMapping((T) o, false);
            dealDefaultValueWithAnnotation(o);
        }

        logger.info("find the limit count is {}", list.size());

        return list;
    }

    /**
     * 针对数据重新排序，只有存在相同排序号的时候才需要重新排序
     * <p>
     * 重新排序的规则是比当前的序列号大的，均加1
     * <p>
     * 必须提供showOrder注解
     *
     * @param t
     * @param entityList
     * @param <T>
     */
    public <T extends AbstractEntity> void modifyShowOrder(T t, List<T> entityList) throws Exception {
        if (t.getId() == null) {
            logger.info("the entity id is null");
            return;
        }

        logger.info("item list size is {}", entityList.size());
        Integer showOrderInEntity = (Integer) ClassUtil.getInstance().getAnnotationValue(t, ShowOrder.class);
        if (showOrderInEntity == null) {
            logger.info("show order is empty");
            return;
        }

        List<T> sameOrderCatalogList = entityList.stream().filter(p -> {
            try {
                return equals((Integer) ClassUtil.getInstance().getAnnotationValue(p, ShowOrder.class), showOrderInEntity) && !equals(p.id, t.id);
            } catch (Exception e) {
                return false;
            }
        }).collect(Collectors.toList());

        if (isEmpty(sameOrderCatalogList)) {
            logger.info("not find the same order entity");
            return;
        }

        //找到了相同排序的对象，依次排序，添加1
        List<T> modifyItemList = entityList.stream().filter(p -> {
            try {
                return (Integer) ClassUtil.getInstance().getAnnotationValue(p, ShowOrder.class) >= showOrderInEntity && !equals(p.id, t.id);
            } catch (Exception e) {
                return false;
            }
        }).collect(Collectors.toList());

        List<Field> fieldList = ClassUtil.getInstance().findFieldList(t, ShowOrder.class);
        Field showOrderField = fieldList.get(0);

        for (T modifyItem : modifyItemList) {
            Integer showOrder = (Integer) showOrderField.get(modifyItem);
            showOrderField.set(modifyItem, showOrder + 1);
            logger.info("will moidy item {} show order");
            save(modifyItem);
        }
    }

    /**
     * 查询查询没有被删除的对象，以及备份对象的标记
     *
     * @param entity
     */
    private void addDeleteFlagAndEntity(AbstractEntity entity) {
        if (entity.getFlagDelete() == null) {
            entity.setFlagDelete(false);
        }

        if (entity.getContainBackupEntity() == null) {
            entity.setEntity(true);
        }
    }

}
